<?php

namespace App\Repositories\Permission;

use App\Models\Permission;
use App\Models\Role;
use App\Repositories\BaseRepository;
use Illuminate\Support\Facades\Cache;

/**
 * 权限仓储类
 * @method Permission|null getById(int $id): ?Permission
 * @method Permission|null create(array $attributes): ?Permission
 */
class PermissionRepository extends BaseRepository
{
    public function __construct(Permission $model)
    {
        parent::__construct($model);
    }

    public function getPermissions(): array
    {
        $transform = function ($row) use (&$transform) {
            return [
                'title' => $row->title,
                'icon' => $row->icon,
                'name' => $row->name,
                'active' => $row->active,
                'redirect' => $row->redirect,
                'children' => $row->children->map($transform)->toArray()
            ];
        };

        $query = Permission::query()->with('children')->where('status', 1)->where('parent_id', 0);
        return $query->orderBy('sort')
            ->get()
            ->map($transform)
            ->toArray();
    }


    public function getCachePermissions(Role $role): array
    {
        $cacheKey = 'role_permissions_' . $role->id;
        return Cache::remember($cacheKey, now()->addHours(24), function () use ($role) {
            $permissionIds = collect($role->getPermissionIds());
            if ($permissionIds->isEmpty()) {
                return [];
            }

            // 只选择需要的字段，减少内存占用
            $allPermissions = Permission::query()
                ->select(['id', 'parent_id', 'title', 'icon', 'name', 'active', 'redirect', 'sort'])
                ->where('status', 1)
                ->whereIn('id', $permissionIds)
                ->orderBy('sort')
                ->get();

            // 转换为数组减少对象开销
            $permissionsArray = $allPermissions->toArray();
            $groupedByParent = collect($permissionsArray)->groupBy('parent_id');
            $permissionIdsSet = $permissionIds->flip(); // 用于O(1)查找

            $buildTree = function ($parentId) use (&$buildTree, $groupedByParent, $permissionIdsSet) {
                $children = $groupedByParent->get($parentId, []);
                $result = [];

                foreach ($children as $permission) {
                    $childNodes = $buildTree($permission['id']);

                    if (!empty($childNodes) || isset($permissionIdsSet[$permission['id']])) {
                        $result[] = [
                            'title' => $permission['title'],
                            'icon' => $permission['icon'],
                            'name' => $permission['name'],
                            'active' => $permission['active'],
                            'redirect' => $permission['redirect'],
                            'children' => $childNodes
                        ];
                    }
                }

                return $result;
            };

            return $buildTree(0);
        });

    }

    public function tree(): array
    {
        $transform = function ($row) use (&$transform) {
            return [
                'id' => $row->id,
                'parent_id' => $row->parent_id,
                'title' => $row->title,
                'icon' => $row->icon,
                'name' => $row->name,
                'active' => $row->active,
                'redirect' => $row->redirect,
                'type' => $row->type,
                'is_show' => $row->is_show,
                'slug' => $row->slug,
                'sort' => $row->sort,
                'status' => $row->status,
                'created_at' => $row->created_at ? $row->created_at->format('Y-m-d') : null,
                'children' => $row->children->map($transform)->toArray()
            ];
        };

        $query = Permission::query()->with('children')->where('parent_id', 0);
        return $query->orderBy('sort')
            ->get()
            ->map($transform)
            ->toArray();
    }

    public function getSelect(): array
    {
        $transform = function ($row) use (&$transform) {
            return [
                'id' => $row->id,
                'parent_id' => $row->parent_id,
                'title' => $row->title,
                'children' => $row->children->map($transform)->toArray()
            ];
        };
        return Permission::query()->with('children')->where('status', 1)->where('parent_id', 0)
            ->get(['id', 'title', 'parent_id'])->map($transform)
            ->toArray();
    }

}
